﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Text.RegularExpressions;
using BusinessPlatformTool.BusinessObjectStructure;

namespace BusinessPlatformTool.CodeFiles
{
    internal static class CreateCodeFiles
    {
        /// <summary>
        /// 获取数据类型
        /// </summary>
        /// <param name="field"></param>
        /// <returns></returns>
        private static string GetPropertyType(IField field)
        {
            if (field.PropertyType == field.DbType.ToString())
                return BusinessPlatform.Common.ConvertEx.ToSystemType(ConvertEx.ToSystemType(field.DbType)).ToString();
            else
            {
                int value;
                if (GetSystemEnum().TryGetValue(field.PropertyType, out value))
                    return "BusinessPlatform.Data.Enumerator." + field.PropertyType;
                else
                    return "Data.Enumerator." + field.PropertyType;
            }
        }
        /// <summary>
        /// 创建接口文件
        /// </summary>
        /// <param name="BusObj"></param>
        /// <param name="NameSpacePath"></param>
        /// <param name="Path"></param>
        /// <param name="table"></param>
        private static void CreateInterface(IBusinessObject BusObj, string NameSpacePath, string Path, ITable table)
        {
            string Note = string.Empty;
            //模板内容
            Note = File.OpenText(Path + "Interface.txt").ReadToEnd();
            #region 固定值
            //命名空间
            Note = Note.Replace("%Namespace%", BusObj.NameSpace);
            //接口描述
            Note = Note.Replace("%InterfaceDescription%", table.Description);
            //接口名称
            Note = Note.Replace("%InterfaceName%", "I" + table.ClassName);
            #endregion
            #region 属性值
            Regex re = new Regex(@"<\$Property\$>(.*)<\/\$Property\$>", RegexOptions.Singleline | RegexOptions.ExplicitCapture);
            string TemplateString = re.Matches(Note)[0].Value;
            string PropertiesString = TemplateString;
            TemplateString = TemplateString.Replace("<$Property$>", "");
            TemplateString = TemplateString.Replace("</$Property$>", "");
            string Properties = string.Empty;
            foreach (var field in table.Lines)
            {
                Properties += TemplateString
                    .Replace("%PropertyDescription%", field.Description)
                    .Replace("%PropertyType%", GetPropertyType(field))
                    .Replace("%PropertyName%", field.PropertyName);
            }
            Note = Note.Replace(PropertiesString, Properties);
            #endregion
            #region  属性中的集合类型
            if (BusObj.Lines.Count > 0 && table.IsPrimary)
            {
                re = new Regex(@"<\$Collection\$>(.*)<\/\$Collection\$>", RegexOptions.Singleline | RegexOptions.ExplicitCapture);
                TemplateString = re.Matches(Note)[0].Value;
                PropertiesString = TemplateString;
                TemplateString = TemplateString.Replace("<$Collection$>", "");
                TemplateString = TemplateString.Replace("</$Collection$>", "");
                Properties = string.Empty;
                foreach (var item in BusObj.Lines.GetChildTable())
                {
                    //集合类型
                    Properties += TemplateString
                        .Replace("%CollectionDescription%", item.Description)
                        .Replace("%CollectionType%", "I" + item.ClassName + "s")
                        .Replace("%CollectionName%", item.ClassName + "s");
                }
                Note = Note.Replace(PropertiesString, Properties);
            }
            else
            {
                re = new Regex(@"<\$Collection\$>(.*)<\/\$Collection\$>", RegexOptions.Singleline | RegexOptions.ExplicitCapture);
                TemplateString = re.Matches(Note)[0].Value;
                Note = Note.Replace(TemplateString, "");
            }
            #endregion
            var sw = File.CreateText(NameSpacePath + "\\I" + table.ClassName + ".cs");
            sw.Write(Note);
            sw.Flush();
            sw.Close();
            sw.Dispose();
        }
        /// <summary>
        /// 他们集合接口文件
        /// </summary>
        /// <param name="BusObj"></param>
        /// <param name="NameSpacePath"></param>
        /// <param name="Path"></param>
        /// <param name="table"></param>
        private static void CreateCollectionInterface(IBusinessObject BusObj, string NameSpacePath, string Path, ITable table)
        {
            string Note = string.Empty;
            //模板内容
            Note = File.OpenText(Path + "InterfaceLines.txt").ReadToEnd();
            //命名窗体
            Note = Note.Replace("%Namespace%", BusObj.NameSpace);
            //接口描述
            Note = Note.Replace("%InterfaceDescription%", table.Description + "集合");
            //接口名称
            Note = Note.Replace("%InterfaceName%", "I" + table.ClassName + "s");
            //接口文件的子类型
            Note = Note.Replace("%ChildInterfaceName%", "I" + table.ClassName);
            var sw = File.CreateText(NameSpacePath + "\\I" + table.ClassName + "s.cs");
            sw.Write(Note);
            sw.Flush();
            sw.Close();
            sw.Dispose();
        }
        /// <summary>
        /// 创建实体类文件
        /// </summary>
        /// <param name="BusObj"></param>
        /// <param name="NameSpacePath"></param>
        /// <param name="Path"></param>
        /// <param name="table"></param>
        private static void CreateClass(IBusinessObject BusObj, string NameSpacePath, string Path, ITable table)
        {
            string Note = string.Empty;
            //模板内容
            Note = File.OpenText(Path + "Class.txt").ReadToEnd();
            #region 固定值
            //命名空间
            Note = Note.Replace("%Namespace%", BusObj.NameSpace);
            //类描述
            Note = Note.Replace("%ClassDescription%", table.Description);
            //类名称
            Note = Note.Replace("%ClassName%", table.ClassName);
            //接口
            Note = Note.Replace("%InterfaceName%", "I" + table.ClassName);
            //业务类型
            Note = Note.Replace("%BusinessObjectType%", "I" + table.Type.ToString());
            //数据表描述
            Note = Note.Replace("%TableDescription%", table.Description);
            //数据表
            Note = Note.Replace("%TableName%", table.Name);
            #endregion
            #region 属性值
            Regex re = new Regex(@"<\$Property\$>(.*)<\/\$Property\$>", RegexOptions.Singleline | RegexOptions.ExplicitCapture);
            string TemplateString = re.Matches(Note)[0].Value;
            string PropertiesString = TemplateString;
            TemplateString = TemplateString.Replace("<$Property$>", "");
            TemplateString = TemplateString.Replace("</$Property$>", "");
            string Properties = string.Empty;
            foreach (var field in table.Lines)
            {
                Properties += TemplateString
                    .Replace("%PropertyDescription%", field.Description)//属性描述
                    .Replace("%PropertyType%", GetPropertyType(field))//属性类型
                    .Replace("%PropertyName%", field.PropertyName)//属性名称
                    .Replace("%FieldName%", field.Name)//字段名称
                    .Replace("%DbType%", ConvertEx.ToSystemType(field.DbType).ToString())//字段类型
                    .Replace("%DefaultValue%", string.IsNullOrWhiteSpace(field.DefaultValue) == false ? ", DefaultValue = \"" + field.DefaultValue + "\"" : "")//默认值
                    .Replace("%IsPrimary%", field.IsPrimaryKey == true ? ", IsPrimary = true" : "")//主键
                    .Replace("%IsUnionKey%", field.IsUnionKey == true ? ", IsUnionKey = true" : "")//联合主键
                    ;
            }
            Note = Note.Replace(PropertiesString, Properties);
            #endregion
            #region  属性中的集合类型
            if (BusObj.Lines.Count > 0 && table.IsPrimary)
            {
                re = new Regex(@"<\$Collection\$>(.*)<\/\$Collection\$>", RegexOptions.Singleline | RegexOptions.ExplicitCapture);
                TemplateString = re.Matches(Note)[0].Value;
                PropertiesString = TemplateString;
                TemplateString = TemplateString.Replace("<$Collection$>", "");
                TemplateString = TemplateString.Replace("</$Collection$>", "");
                Properties = string.Empty;
                foreach (var item in BusObj.Lines.GetChildTable())
                {
                    //集合类型
                    Properties += TemplateString
                        .Replace("%CollectionDescription%", item.Description)
                        .Replace("%ChildInterface%", "I" + item.ClassName + "s")
                        .Replace("%ChildVariablePrivate%", "_" + item.ClassName + "s")
                        .Replace("%ChildVariablePublic%", item.ClassName + "s")
                        ;
                }
                Note = Note.Replace(PropertiesString, Properties);
            }
            else
            {
                re = new Regex(@"<\$Collection\$>(.*)<\/\$Collection\$>", RegexOptions.Singleline | RegexOptions.ExplicitCapture);
                TemplateString = re.Matches(Note)[0].Value;
                Note = Note.Replace(TemplateString, "");
            }
            #endregion
            #region 构造函数
            if (BusObj.Lines.Count > 0 && table.IsPrimary)
            {
                re = new Regex(@"<\$Constrctor\$>(.*)<\/\$Constrctor\$>", RegexOptions.Singleline | RegexOptions.ExplicitCapture);
                TemplateString = re.Matches(Note)[0].Value;
                PropertiesString = TemplateString;
                TemplateString = TemplateString.Replace("<$Constrctor$>", "");
                TemplateString = TemplateString.Replace("</$Constrctor$>", "");
                Properties = string.Empty;
                foreach (var item in BusObj.Lines.GetChildTable())
                {
                    //集合类型
                    Properties += TemplateString
                        .Replace("%ChildVariablePrivate%", "_" + item.ClassName + "s")
                        .Replace("%ChildClass%", item.ClassName + "s")
                        .Replace("%ChildInterface%", "I" + item.ClassName + "s")
                        .Replace("%ChildVariablePublic%", item.ClassName + "s")
                        ;
                }
                Note = Note.Replace(PropertiesString, Properties);
            }
            else
            {
                re = new Regex(@"<\$Constrctor\$>(.*)<\/\$Constrctor\$>", RegexOptions.Singleline | RegexOptions.ExplicitCapture);
                TemplateString = re.Matches(Note)[0].Value;
                Note = Note.Replace(TemplateString, "");
            }
            #endregion
            var sw = File.CreateText(NameSpacePath + "\\" + table.ClassName + ".cs");
            sw.Write(Note);
            sw.Flush();
            sw.Close();
            sw.Dispose();
        }
        /// <summary>
        /// 创建实体类集合文件
        /// </summary>
        /// <param name="BusObj"></param>
        /// <param name="NameSpacePath"></param>
        /// <param name="Path"></param>
        /// <param name="table"></param>
        private static void CreateCollectionClass(IBusinessObject BusObj, string NameSpacePath, string Path, ITable table)
        {
            string Note = string.Empty;
            //模板内容
            Note = File.OpenText(Path + "ClassLines.txt").ReadToEnd();
            //命名窗体
            Note = Note.Replace("%Namespace%", BusObj.NameSpace);
            //接口描述
            Note = Note.Replace("%ClassDescription%", table.Description + "集合");
            //接口名称
            Note = Note.Replace("%ClassName%", table.ClassName + "s");
            //接口的父类型
            Note = Note.Replace("%ParentInterfaceName%", "I" + BusObj.Lines.GetPrimaryTable().ClassName);
            //继承的接口
            Note = Note.Replace("%InterfaceName%", "I" + table.ClassName + "s");
            //接口文件的子类型
            Note = Note.Replace("%ChildInterfaceName%", "I" + table.ClassName);
            //子类
            Note = Note.Replace("%ChildClassName%", table.ClassName);
            var sw = File.CreateText(NameSpacePath + "\\" + table.ClassName + "s.cs");
            sw.Write(Note);
            sw.Flush();
            sw.Close();
            sw.Dispose();
        }
        /// <summary>
        /// 创建代码文件
        /// </summary>
        /// <param name="BOPath"></param>
        /// <param name="BusObj"></param>
        public static void CreateFiles(IBusinessObject BusObj, string BOPath)
        {
            #region 创建对象的文件夹
            var NameSpacePath = BOPath + "\\" + BusObj.NameSpace;
            Directory.CreateDirectory(NameSpacePath);
            #endregion
            var TempPath = System.Windows.Forms.Application.StartupPath + "\\Template\\CodeStructure\\";
            #region 创建Models文件
            foreach (var table in BusObj.Lines)
            {
                //创建接口文件
                CreateInterface(BusObj, NameSpacePath, TempPath + "Interface\\", table);
                //创建类型文件
                CreateClass(BusObj, NameSpacePath, TempPath + "Class\\", table);
            }
            #region 集合接口
            foreach (var table in BusObj.Lines.GetChildTable())
            {
                //创建接口文件
                CreateCollectionInterface(BusObj, NameSpacePath, TempPath + "Interface\\", table);
                //创建类型文件
                CreateCollectionClass(BusObj, NameSpacePath, TempPath + "Class\\", table);
            }
            #endregion
            #endregion
            #region 创建数据类型枚举

            #endregion
        }
        /// <summary>
        /// 获取系统的枚举类型
        /// </summary>
        /// <returns></returns>
        private static IDictionary<string, int> GetSystemEnum()
        {
            IDictionary<string, int> DicSystemEnum = new Dictionary<string, int>();
            Type EnumType = typeof(BusinessPlatform.Data.Enumerator);
            foreach (var Enum in EnumType.GetNestedTypes())
            {
                DicSystemEnum.Add(Enum.Name, Enum.GetEnumNames().Length);
            }
            return DicSystemEnum;
        }
        /// <summary>
        /// 创建枚举文件
        /// </summary>
        /// <param name="EnumType"></param>
        /// <param name="BOPath"></param>
        public static void CreateEnum(IDictionary<string, IValidDataType> EnumType, string BOPath)
        {
            foreach (var SysEnum in GetSystemEnum())
            {
                if (EnumType.ContainsKey(SysEnum.Key))
                    EnumType.Remove(SysEnum.Key);
            }
            if (EnumType.Count <= 0)
                return;
            #region 创建枚举的文件夹
            var NameSpacePath = BOPath + "\\Data";
            Directory.CreateDirectory(NameSpacePath);
            #endregion
            var TempPath = System.Windows.Forms.Application.StartupPath + "\\Template\\CodeStructure\\Enum\\Enum.txt";
            string Note = string.Empty;
            //模板内容
            Note = File.OpenText(TempPath).ReadToEnd();
            //命名空间
            Note = Note.Replace("%Namespace%", "Data");
            #region 枚举类型
            Regex EnumTypere = new Regex(@"<\$Enum\$>(.*)<\/\$Enum\$>", RegexOptions.Singleline | RegexOptions.ExplicitCapture);
            string TemplateString = EnumTypere.Matches(Note)[0].Value;
            string EnumTypeString = TemplateString;
            TemplateString = TemplateString.Replace("<$Enum$>", "");
            TemplateString = TemplateString.Replace("</$Enum$>", "");
            string Properties = string.Empty;
            foreach (var Enum in EnumType)
            {
                IValidDataType DataType = Enum.Value;
                Properties += TemplateString
                    .Replace("%EnumTypeDescription%", "")//属性描述
                    .Replace("%EnumTypeName%", DataType.DataTypeName)//属性类型                   
                    ;
                Regex EnumItemre = new Regex(@"<\$EnumItem\$>(.*)<\/\$EnumItem\$>", RegexOptions.Singleline | RegexOptions.ExplicitCapture);
                string EnumItemTemplateString = EnumItemre.Matches(Properties)[0].Value;
                string EnumItemString = EnumItemTemplateString;
                EnumItemTemplateString = EnumItemTemplateString.Replace("<$EnumItem$>", "");
                EnumItemTemplateString = EnumItemTemplateString.Replace("</$EnumItem$>", "");
                string EnumItem = string.Empty;

                foreach (IValidValue item in DataType.lines)
                {
                    EnumItem += EnumItemTemplateString
                        .Replace("%EnumValue%", item.ValidValue)//值
                        .Replace("%EnumDescription%", item.ValidDescription)//描述
                        .Replace("%EnumName%", item.ValidName)//类型
                        ;
                }
                Properties = Properties.Replace(EnumItemString, EnumItem);
            }
            Note = Note.Replace(EnumTypeString, Properties);
            #endregion
            var sw = File.CreateText(NameSpacePath + "\\Enumerator.cs");
            sw.Write(Note);
            sw.Flush();
            sw.Close();
            sw.Dispose();
        }
    }
}
